def _listify(src_dict, src_key):
    if src_dict.has_key(src_key):
        src_val = src_dict[src_key]
        if isinstance(src_val, list):
            return src_val
        elif isinstance(src_val, str):
            return [src_val]
    return []

class Snippet:
    def __init__(self, data):
        self.name = data['name']
        self.params = _listify(data, 'params')
        self.textures = _listify(data, 'textures')
        self.vertex = _listify(data, 'vertex')
        self.interpolators = _listify(data, 'interpolators')

    @staticmethod
    def from_file(src_file_name):
        src_file = open(src_file_name)
        try:
            return Snippet(eval(src_file.read())[0])
        finally:
            src_file.close()

class SnippetCombiner:
    def __init__(self, snips):
        self.snips = snips

    def snip_iterator(self, snip_func):
        for index, snip in enumerate(self.snips):
            snip_func(index, snip)

    def snip_init(self, index, snip):
        snip.name = snip.data['name']+str(index)
        snip.textures = dict((texture, snip.name+'_'+texture) for texture in snip.data['textures'])
        snip.interpolators = dict((interp, snip.data[interp]) for interp in snip.data['interpolators'])

    def emit_per_snippet_textures(self, index, snip):
        print '// '+snip.name+' textures'
        for _, texture in snip.textures.iteritems():
            print 'sampler '+texture+'\n'

    def emit_per_snippet_input_structure(self, index, snip):
        snip.input_structure_name = snip.name+'_INPUT'
        print 'struct '+snip.input_structure_name+'\n{'
        for interp, interptype in snip.interpolators.iteritems():
            use_color_interpolator = 'color' == interptype
            if use_color_interpolator:
                print '    float%d %s : COLOR%d;' % (interptype, interp, self.used_color_interpolators)
                self.used_color_interpolators += 1
            else:
                print '    float%d %s : TEXCOORD%d;' % (interptype, interp, self.used_texture_interpolators)
                self.used_texture_interpolators += 1                
        print '};\n'

    def emit_pixel_shader_input_structure(self, index, snip):
        print '    '+snip.input_structure_name+' '+snip.name
        
    def combine(self):
        self.snip_iterator(self.snip_init)

        self.snip_iterator(self.emit_per_snippet_textures)

        print '// -------- input structures --------'
        self.used_color_interpolators = 0
        self.used_texture_interpolators = 0
        self.snip_iterator(self.emit_per_snippet_input_structure)
        print 'struct INPUT\n{'
        self.snip_iterator(self.emit_pixel_shader_input_structure)
        print '};\n\nINPUT gInput;\n'
